/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cn.ekuma.epos.datalogic.businesslogic;

import cn.ekuma.epos.datalogic.I_DataLogicERP;
import cn.ekuma.epos.datalogic.businesslogic.orderprocess.I_OrderProcess;
import cn.ekuma.epos.datalogic.businesslogic.orderprocess.I_OrderProcessFlow;
import cn.ekuma.epos.datalogic.businesslogic.orderprocess.I_ProcessManager;
import cn.ekuma.epos.datalogic.businesslogic.orderprocess.impl.DefalutOrderProcessFlow;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.openbravo.bean.erp.Order;
import com.openbravo.bean.erp.OrderType;
import com.openbravo.data.basic.BasicException;
import com.openbravo.data.loader.I_Session;
import com.openbravo.data.loader.Transaction;

import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.util.PluginManagerUtil;

/**
 * 
 * @author Administrator
 */
public class OrderProcessManager implements I_ProcessManager {
	public static String LOCAL_Prefix = "orderProcess.";

	private Map<String, I_OrderProcessFlow> processFlowMap = new HashMap<String, I_OrderProcessFlow>();

	private Map<String, I_OrderProcess> processMap = new HashMap<String, I_OrderProcess>();

	public OrderProcessManager(Collection<I_OrderProcessFlow> plugins,Collection<I_OrderProcess> orderProcessPlugins) {
		DefalutOrderProcessFlow aProcess = new DefalutOrderProcessFlow();
		processFlowMap.put(aProcess.getName(), aProcess);
		
		if(plugins!=null)
		for (I_OrderProcessFlow orderProcessFlow : plugins) {
			processFlowMap.put(orderProcessFlow.getName(), orderProcessFlow);
		}
		
        if(orderProcessPlugins!=null)
		for (I_OrderProcess orderProcess : orderProcessPlugins) {
			processMap.put(orderProcess.getName(), orderProcess);
		}
	}

	public OrderProcessManager() {
		this(null,null);
	}

	@Override
	public void saveOrder(final I_DataLogicERP dlERP, final Order order)
			throws BasicException {
		String processName = order.getDefineType().getProcessName();
		final OrderType oType = order.getDefineType();
		if (processName == null)
			processName = I_OrderProcessFlow.PROCESSTYPE_Default;
		final I_OrderProcessFlow orderProcessFlow = getProcessFlow(processName);
		;
		if (orderProcessFlow == null)
			throw new BasicException(
					"not support this order process,are you defined?");
		final I_Session s = dlERP.getSession();
		final List<String> selectedOrderProcess = dlERP
				.findOrderSuperedProcessByOrderType(oType.getId());
		Transaction t = new Transaction(s) {
			public Object transact() throws BasicException {
				orderProcessFlow.saveOrder(dlERP, order);
				for (String oProcess : selectedOrderProcess) {
					I_OrderProcess process = getProcess(oProcess);
					if (process != null)
						process.saveOrder(dlERP, order);
					else
						throw new BasicException("selected process no defined");
				}
				return null;
			}
		};
		t.execute();
	}

	@Override
	public Order loadOrder(final I_DataLogicERP dlERP, final String orderid)
			throws BasicException {
		String processName = null;// order.getDefineType().getProcessName();
		Order order = null;
		final I_Session s = dlERP.getSession();
		if (processName == null)
			processName = I_OrderProcessFlow.PROCESSTYPE_Default;
		final I_OrderProcessFlow orderProcessFlow = getProcessFlow(processName);
		if (orderProcessFlow == null)
			throw new BasicException(
					"not support this order process,are you defined?");
		order = orderProcessFlow.loadOrder(dlERP, orderid);
		OrderType oType = order.getDefineType();
		final List<String> selectedOrderProcess = dlERP
				.findOrderSuperedProcessByOrderType(oType.getId());
		for (String oProcess : selectedOrderProcess) {
			I_OrderProcess process = getProcess(oProcess);
			if (process != null)
				process.saveOrder(dlERP, order);
			else
				throw new BasicException("selected process no defined");
		}
		return order;
	}

	@Override
	public void deleteOrder(final I_DataLogicERP dlERP, final Order order)
			throws BasicException {
		final I_Session s = dlERP.getSession();
		String processName = order.getDefineType().getProcessName();
		if (processName == null)
			processName = I_OrderProcessFlow.PROCESSTYPE_Default;
		final I_OrderProcessFlow orderProcessFlow = getProcessFlow(processName);
		;
		if (orderProcessFlow == null)
			throw new BasicException(
					"not support this order process,are you defined?");
		Transaction t = new Transaction(s) {
			public Object transact() throws BasicException {
				orderProcessFlow.deleteOrder(dlERP, order);
				OrderType oType = order.getDefineType();
				final List<String> selectedOrderProcess = dlERP
						.findOrderSuperedProcessByOrderType(oType.getId());
				for (String oProcess : selectedOrderProcess) {
					I_OrderProcess process = getProcess(oProcess);
					if (process != null)
						process.deleteOrder(dlERP, order);
					else
						throw new BasicException("selected process no defined");
				}
				return null;
			}
		};
		t.execute();
	}

	public I_OrderProcessFlow getProcessFlow(String processName) {
		return processFlowMap.get(processName);
	}

	public Map<String, I_OrderProcessFlow> getProcesFlowMap() {
		return processFlowMap;
	}

	@Override
	public Map<String, I_OrderProcess> getProcesMap() {
		return processMap;
	}

	@Override
	public I_OrderProcess getProcess(String processName) {
		return processMap.get(processName);
	}


	@Override
	public HashMap<String, String> getOrderProcessProp(I_DataLogicERP dlSales,
			String orderTypeId, String processName) throws BasicException {
		I_OrderProcess orderProcess = processMap.get(processName);
		if (orderProcess == null)
			throw new BasicException("no found orderProcess in local plugins:"
					+ processName);
		HashMap ret = dlSales.findOrderProcessPropByNameAndOrderType(
				orderTypeId, processName);
		if (ret == null)
			ret = orderProcess.getConfigProp();
		return ret;
	}

	public List<String> getAllOrderProcess() throws BasicException {
		List<String> ret = new ArrayList();
		for (String processName : processMap.keySet())
			ret.add(processName);
		return ret;
	}

}
